package org.linloong.modules.apis.monitor.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import lombok.RequiredArgsConstructor;
import org.linloong.modules.apis.monitor.dto.RealTimeAggDTO;
import org.linloong.modules.apis.monitor.entity.DailyAggStats;
import org.linloong.modules.apis.monitor.entity.DeviceGroup;
import org.linloong.modules.apis.monitor.dto.MultiSensorWithUnitAggDTO;
import org.linloong.modules.apis.monitor.entity.WeatherDataParsed;
import org.linloong.modules.apis.monitor.mapper.DailyAggStatsMapper;
import org.linloong.modules.apis.monitor.mapper.DeviceGroupMapper;
import org.linloong.modules.apis.monitor.mapper.WeatherDataParsedMapper;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RealTimeAggregationService {

    private final DeviceGroupMapper deviceGroupMapper;
    private final WeatherDataParsedMapper parsedDataMapper;
    private final DailyAggStatsMapper dailyAggStatsMapper;

    /**
     * 查询指定设备分组的月度数据（多传感器带单位，前端指定格式）
     */
    public List<MultiSensorWithUnitAggDTO> queryMultiSensorMonthData(String groupId) {
        // 1. 校验设备分组
        DeviceGroup group = deviceGroupMapper.selectById(groupId);
        if (group == null) {
            throw new IllegalArgumentException("设备分组不存在：" + groupId);
        }

        // 2. 查询该分组所有每日统计数据
        List<DailyAggStats> statsList = dailyAggStatsMapper.selectList(
                new LambdaQueryWrapper<DailyAggStats>()
                        .eq(DailyAggStats::getGroupId, groupId)
                        .orderByAsc(DailyAggStats::getStatDate)
        );
        if (statsList.isEmpty()) {
            return new ArrayList<>();
        }

        // 3. 按"年份→月份→serial"分组，计算月度平均值
        // 数据结构：year → month → serial → (name, unit, 每日值列表)
        Map<Integer, Map<Integer, Map<Integer, SensorTempData>>> yearMonthSerialMap = new HashMap<>();

        for (DailyAggStats stats : statsList) {
            LocalDate date = stats.getStatDate();
            int year = date.getYear();
            int month = date.getMonthValue();
            int serial = stats.getSerial();

            // 初始化分组结构
            yearMonthSerialMap.computeIfAbsent(year, k -> new HashMap<>())
                    .computeIfAbsent(month, k -> new HashMap<>())
                    .computeIfAbsent(serial, k -> {
                        // 存储传感器基本信息（name, unit）和每日值列表
                        SensorTempData tempData = new SensorTempData();
                        tempData.setName(stats.getSensorName());
                        tempData.setUnit(stats.getUnit());
                        tempData.setDailyValues(new ArrayList<>());
                        return tempData;
                    })
                    .getDailyValues()
                    .add(stats.getAvgValue());
        }

        // 4. 转换为前端格式
        List<MultiSensorWithUnitAggDTO> result = new ArrayList<>();

        // 遍历年份
        for (Map.Entry<Integer, Map<Integer, Map<Integer, SensorTempData>>> yearEntry : yearMonthSerialMap.entrySet()) {
            Integer year = yearEntry.getKey();
            Map<Integer, Map<Integer, SensorTempData>> monthSerialMap = yearEntry.getValue();

            MultiSensorWithUnitAggDTO yearAgg = new MultiSensorWithUnitAggDTO();
            yearAgg.setYear(year);

            // 遍历月份
            for (Map.Entry<Integer, Map<Integer, SensorTempData>> monthEntry : monthSerialMap.entrySet()) {
                Integer month = monthEntry.getKey();
                Map<Integer, SensorTempData> serialDataMap = monthEntry.getValue();

                MultiSensorWithUnitAggDTO.MonthSensorData monthData = new MultiSensorWithUnitAggDTO.MonthSensorData(month.toString());

                // 遍历该月份下的所有传感器（按serial区分）
                for (SensorTempData tempData : serialDataMap.values()) {
                    // 计算月度平均值
                    BigDecimal monthAvg = calculateAvg(tempData.getDailyValues());
                    // 构建传感器数据（含单位）
                    MultiSensorWithUnitAggDTO.SensorData sensorData = new MultiSensorWithUnitAggDTO.SensorData(
                            tempData.getName(),
                            monthAvg.setScale(2, BigDecimal.ROUND_HALF_UP).toString(),
                            tempData.getUnit()
                    );
                    monthData.getSensor().add(sensorData);
                }

                yearAgg.getData().add(monthData);
            }

            // 月度数据按月份降序排序
            yearAgg.getData().sort((m1, m2) -> Integer.compare(
                    Integer.parseInt(m2.getMonth()),
                    Integer.parseInt(m1.getMonth())
            ));

            result.add(yearAgg);
        }

        // 年份按降序排序
        result.sort((y1, y2) -> Integer.compare(y2.getYear(), y1.getYear()));

        return result;
    }

    /**
     * 临时存储传感器数据（用于计算月度平均值）
     */
    private static class SensorTempData {
        private String name;
        private String unit;
        private List<BigDecimal> dailyValues;

        // getter/setter
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getUnit() { return unit; }
        public void setUnit(String unit) { this.unit = unit; }
        public List<BigDecimal> getDailyValues() { return dailyValues; }
        public void setDailyValues(List<BigDecimal> dailyValues) { this.dailyValues = dailyValues; }
    }

    /**
     * 实时计算指定设备分组的年月平均值
     * @param groupId 设备分组ID
     * @return 包含年度和月度平均值的聚合结果
     */
    public RealTimeAggDTO calculateGroupAggregation(String groupId) {
        // 1. 校验设备分组是否存在
        DeviceGroup group = deviceGroupMapper.selectById(groupId);
        if (group == null) {
            throw new IllegalArgumentException("设备分组不存在：" + groupId);
        }
        List<String> deviceIds = Arrays.asList(group.getDeviceIds().split(","));
        if (deviceIds.isEmpty()) {
            throw new IllegalArgumentException("设备分组未关联任何设备：" + groupId);
        }

        // 2. 查询该分组下所有设备的解析数据（带索引优化）
        List<WeatherDataParsed> allData = parsedDataMapper.selectList(
                new LambdaQueryWrapper<WeatherDataParsed>()
                        .in(WeatherDataParsed::getDeviceId, deviceIds)
                        // 按设备+时间排序，便于后续分组
                        .orderByAsc(WeatherDataParsed::getDeviceId, WeatherDataParsed::getTimestamp)
        );

        // 3. 解析时间维度（年份和月份）并分组
        // 数据格式：(年份, 月份, 指标名称) → 数值列表
        Map<String, List<BigDecimal>> dataGroups = allData.stream()
                .collect(Collectors.groupingBy(
                        data -> {
                            // 从timestamp提取年份和月份
                            Instant instant = Instant.ofEpochMilli(data.getTimestamp());
                            int year = instant.atZone(ZoneId.systemDefault()).getYear();
                            int month = instant.atZone(ZoneId.systemDefault()).getMonthValue();
                            // 分组键：年份_月份_指标名称（如"2024_3_温度"）
                            return year + "_" + month + "_" + data.getSensorName();
                        },
                        // 收集每个分组的数值列表
                        Collectors.mapping(WeatherDataParsed::getParsedValue, Collectors.toList())
                ));

        // 4. 计算月度平均值
        Map<Integer, Map<Integer, Map<String, BigDecimal>>> monthlyAvg = new HashMap<>();
        // 计算年度平均值（基于月度数据）
        Map<Integer, Map<String, List<BigDecimal>>> tempYearlyData = new HashMap<>();

        for (Map.Entry<String, List<BigDecimal>> entry : dataGroups.entrySet()) {
            String[] keyParts = entry.getKey().split("_");
            int year = Integer.parseInt(keyParts[0]);
            int month = Integer.parseInt(keyParts[1]);
            String indicator = keyParts[2];
            List<BigDecimal> values = entry.getValue();

            // 计算月度平均值
            BigDecimal monthAvg = calculateAvg(values);
            // 存入月度Map
            monthlyAvg.computeIfAbsent(year, k -> new HashMap<>())
                    .computeIfAbsent(month, k -> new HashMap<>())
                    .put(indicator, monthAvg);

            // 收集月度平均值到年度临时Map，用于计算年度平均
            tempYearlyData.computeIfAbsent(year, k -> new HashMap<>())
                    .computeIfAbsent(indicator, k -> new ArrayList<>())
                    .add(monthAvg);
        }

        // 5. 计算年度平均值（基于月度平均值）
        Map<Integer, Map<String, BigDecimal>> yearlyAvg = new HashMap<>();
        tempYearlyData.forEach((year, indicatorMap) -> {
            Map<String, BigDecimal> yearAvgMap = new HashMap<>();
            indicatorMap.forEach((indicator, monthAvgs) -> {
                yearAvgMap.put(indicator, calculateAvg(monthAvgs));
            });
            yearlyAvg.put(year, yearAvgMap);
        });

        // 6. 包装结果
        RealTimeAggDTO result = new RealTimeAggDTO();
        result.setGroup(group);
        result.setYearlyAvg(yearlyAvg);
        result.setMonthlyAvg(monthlyAvg);
        return result;
    }

    /**
     * 计算列表的平均值（保留2位小数）
     */
    private BigDecimal calculateAvg(List<BigDecimal> values) {
        if (values.isEmpty()) {
            return BigDecimal.ZERO;
        }
        BigDecimal total = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        return total.divide(BigDecimal.valueOf(values.size()), 2, BigDecimal.ROUND_HALF_UP);
    }
}